package com.lvmama.pangolin.proces;


import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.lvmama.pangolin.HBaseOper.MTHBEntityOperation;
import com.lvmama.pangolin.common.Constant;
import com.lvmama.pangolin.common.DateUtil;
import com.lvmama.pangolin.common.RowkeyGenerator;
import com.lvmama.pangolin.common.StringTools;
import com.lvmama.pangolin.conf.ConfigManager;
import com.lvmama.pangolin.entity.ConvertTask;
import com.lvmama.pangolin.entity.RelevanceProduct;
import com.lvmama.pangolin.entity.RuleLevelModel;
import com.lvmama.pangolin.entity.Task_History;
import com.lvmama.pangolin.entity.mt.TicketCdetailMt;
import com.lvmama.pangolin.entity.mt.TicketCommodityMt;
import com.lvmama.pangolin.entity.mt.TicketPdetailMt;
import com.lvmama.pangolin.entity.mt.TicketProductMt;
import com.lvmama.pangolin.hbaseutil.HBaseUtils;
import com.lvmama.pangolin.mt.service.TicketCdetailMtService;
import com.lvmama.pangolin.mt.service.TicketCommodityMtService;
import com.lvmama.pangolin.mt.service.TicketNewProductMtService;
import com.lvmama.pangolin.mt.service.TicketPdetailMtService;
import com.lvmama.pangolin.mt.service.TicketProductMtService;
import com.lvmama.pangolin.service.RelevanceProductService;
import com.lvmama.pangolin.util.RuleUtil;
@Component
public class MTTicketDataProcess {
	/**  
	* @Title：TC_Data_Process.java
	* @Author:zhoutianqi
	* @Description:
	* @Date：2017年2月15日下午3:12:25  
	*/
	private Logger logger = Logger.getLogger(MTTicketDataProcess.class);
	@Autowired
	private TicketCdetailMtService cdetailMtService;
	@Autowired
	private TicketPdetailMtService pdetailMtService;
	@Autowired
	private TicketProductMtService productMtService;
	@Autowired
	private TicketCommodityMtService commodityMtService;
	@Autowired
	private TicketNewProductMtService newProductMtService;
	@Autowired
	private RuleUtil ruleUtil;
	@Autowired
	private ConfigManager configManager;
	@Autowired
	private HBaseUtils hBaseUtil;
	@Autowired
	private MTHBEntityOperation hbentityOper;
	@Autowired
	private RelevanceProductService relevanceProductService;

	@Async
	public String executeProcess(List<ConvertTask> taskList){
		for(ConvertTask task:taskList){
			if(!ruleUtil.hasTaskIDAndCity(task)){
				logger.error("Task任务："+task.getId()+"没有必要的taskID,CityCode");
				ruleUtil.updateTimerStatus(task, Constant.DATA_ERROR_STATE_CODE);
				continue;
			}
			Map<String, String> map = new HashMap<String, String>();
			map.put("taskId", task.getTaskId());
			map.put("cityCode", task.getGranularityValue());
			map.put("productId", task.getProductId());
			try {
				List<TicketPdetailMt> pdetailMtList = pdetailMtService.findListByMap(map);
				List<TicketCdetailMt> cdetailMtList = cdetailMtService.findListByMap(map);
				TicketPdetailMt ticketPdetailMt = null;
				//没找到产品 就下一条
				if(pdetailMtList.isEmpty()){
					continue;
				}
				//没找到商品 就下一条
				if(cdetailMtList.isEmpty()){
					continue;
				}
				//只有一个产品
				ticketPdetailMt = pdetailMtList.get(0);
				//记录成功入库的商品
				List<TicketCdetailMt> checkedDoneList = new ArrayList<>();
				//遍历校验所有商品价格
				//价格防伪流程start
				//是否有新商品
				boolean hasNewCommodity = false;
				for(TicketCdetailMt item:cdetailMtList) {
					if(!StringTools.isValid(item.getSalePrice())){
						continue;
					}
					//商品价格有问题，忽略该商品
					if(!StringTools.isDoubleNumeric(item.getSalePrice())){
						continue;
					}
					//商品类型不能为空
					if(!StringTools.isValid(item.getCommodityType())){continue;}
					//当前商品rowkey
					String rowkey = RowkeyGenerator.generateCommodityRowkey(item.getCommodityId(), item.getCreateTime(), item.getProductId());
					TicketCommodityMt existCommodityMt = commodityMtService.selectById(item.getCommodityId(),item.getProductId());
					/*if(existCommodityMt != null && !item.getCommodityType().equals(existCommodityMt.getCommodityType())){
						//商品类型不一致。忽略.避免出现不同商品类型相同商品ID
						continue;
					}*/
					boolean checkedDone = dataChecke(item,task);
					if(checkedDone){
						synchronized (RuleUtil.class) {
							ruleUtil.addTaskInfo(item.getTaskId(), item.getCreateTime(),Constant.MT_C_CODE,Constant.TICKE_BUS_TYPE,Constant.COMMODITY_LEVEL_TYPE);
						}
						checkedDoneList.add(item);
						if(existCommodityMt!=null){
							//当商品已存在，判断新抓取价格与历史价格是否相等，不相等意味着价格变动
							double historyPrice = Double.parseDouble(existCommodityMt.getSalePrice());
							double currentPrice = Double.parseDouble(item.getSalePrice());
							if(historyPrice!=currentPrice){
								existCommodityMt.setCommPriceChangeNum(existCommodityMt.getCommPriceChangeNum()+1);
								commodityMtService.update(existCommodityMt);
							}
							//抓取数据必须在最后操作，防止历史数据再覆盖回去
							item.setDetailId(existCommodityMt.getId());
							commodityMtService.updateByCdetail(item);
						}else{
							hasNewCommodity = true;
							//统一主键规则
							item.setDetailId(rowkey);
							commodityMtService.saveByCdetail(item);
						}
						// 价格团期数据不存在，存储当前商品价格数据
						hbentityOper.saveMTTicketCommoPrice(item.getTaskId(), item.getCreateTime(),
								item.getSalePrice(), item.getCommodityId(), Constant.TICKET_COMMODITY_PRICE_MT,
								Constant.HB_VARIABLE_FAMILY,item.getProductId());
						// 价格数据入价格历史表 end
						hbentityOper.saveMTTicketCommodity(item, rowkey, Constant.TICKET_COMMODITY_H_MT, Constant.HB_VARIABLE_FAMILY);
					}else{
						//该商品价格校验失败，该条数据入log表
						commodityInsertLog(item, rowkey);
					}
				}
				//如果没有商品入库，忽略产品
				if(checkedDoneList.isEmpty()){
					ruleUtil.updateTimerStatus(task, Constant.DATA_SUCCESS_STATE_CODE);
					continue;
				}
				int commodityTypeNum = handleCommTypeNum(checkedDoneList);
				TicketProductMt param = handelProduct(checkedDoneList);
				param.setCommTypeNum(commodityTypeNum);
				saveProductDirectly(ticketPdetailMt,param,hasNewCommodity);
				ruleUtil.updateTimerStatus(task, Constant.DATA_SUCCESS_STATE_CODE);
				logger.info(">>>>>>当前线程："+Thread.currentThread().getId()+";MT_TICKET任务：["+task.getId()+"];执行完毕！<<<<<<");
			} catch (Exception e) {
				logger.error("MT_Ticket_Data_Process任务处理异常-------任务编码："+task.getId()+"---异常信息："+e.getMessage());
				ruleUtil.updateTimerStatus(task, Constant.DATA_ERROR_STATE_CODE);
			}
		}
		return null;
	}
	public String generateRowkey(String proGooId, Date createDate, String TASKID){
		return RowkeyGenerator.generateRowkey(proGooId, createDate, TASKID);
	}
	
	public boolean dataChecke(TicketCdetailMt item,ConvertTask convertTask){
		List<RuleLevelModel> rulelist = null;
		//考虑任务时间不等于抓取时间情况
		boolean needSuperRule = RuleUtil.needSuperRule(item.getCreateTime(),ruleUtil.getTicketSuperLevelList());
		//新抓取价格,该价格不可能为非法值，前面校验过
		String priceStr = item.getSalePrice();
		double price = Double.parseDouble(priceStr);
		if(needSuperRule){//走特殊防伪
			rulelist = ruleUtil.getTicketSuperLevelList();
		}else{
			rulelist = ruleUtil.getTicketNormalLevelList();
		}
		for(RuleLevelModel level:rulelist){
			List<Task_History> taskList = null;
			List<String> rowkeyList = null;
			int number = 0;
			double totalPrices = 0;
			double average = 0;
			double leftPrice = 0;
			double rightPrice = 0;
			if(needSuperRule){
				if(DateUtil.isRegionDate(item.getCreateTime(), level.getStart_date(), level.getEnd_date())){
					taskList = ruleUtil.getPartOfTask(level.getRule_level(), item.getCreateTime(),Constant.MT_C_CODE,Constant.TICKE_BUS_TYPE,Constant.COMMODITY_LEVEL_TYPE);
					if(taskList!=null){
						rowkeyList = new ArrayList<String>();
						for(Task_History task:taskList){
							rowkeyList.add(RowkeyGenerator.generateCommodityRowkey(item.getCommodityId(), task.getCreate_Date(), item.getProductId()));
						}
						
					}
				}
			}else{
				taskList = ruleUtil.getPartOfTask(level.getRule_level(), item.getCreateTime(),Constant.MT_C_CODE,Constant.TICKE_BUS_TYPE,Constant.COMMODITY_LEVEL_TYPE);
				if(taskList != null && !taskList.isEmpty()){
					rowkeyList = new ArrayList<String>();
					for(Task_History task:taskList){
						rowkeyList.add(RowkeyGenerator.generateCommodityRowkey(item.getCommodityId(), task.getCreate_Date(), item.getProductId()));
					}
				}
			}
			if(rowkeyList!=null){
				List<Map<String, String>> dataList = hBaseUtil
						.get(Constant.TICKET_COMMODITY_H_MT, Constant.HB_VARIABLE_FAMILY, rowkeyList);
				if(dataList.size()>0){
					for(Map<String, String> map:dataList){
						/*根据商品ID拿出所有批次的历史数据
						 * 考虑到存在不同产品ID会有相同商品ID的情况
						 * 在做校验时精确到产品ID和商品类别
						*/
						String currentProductId = map.get("productId");
						String currentCommodityType = map.get("commodityType");
						if (!map.isEmpty() && currentProductId!=null && currentProductId.equals(item.getProductId())
								&& currentCommodityType!=null && currentCommodityType.equals(item.getCommodityType())) {
							String currentPrice = map.get("salePrice");
							if(currentPrice != null && !currentPrice.equals("")){
								totalPrices += Double.parseDouble(currentPrice);
								//避免task-date对应rowkey不存在数据的情况
								number++;
							}
						}
					}
					//因为hbase是通过商品ID拿数据的，存在不同产品的两个商品ID一致的情况
					if(number>0){
						average = totalPrices/number;
						leftPrice = ruleUtil.getLeftPrice(number, average, level.getLeft_value());
						rightPrice = ruleUtil.getRightPrice(number, average, level.getRight_value());
						//当价格超出容忍范围 记录日志
						if(price<leftPrice || price>rightPrice){
							try {
								ruleUtil.insertLogMesg(convertTask, null, item.getCommodityId(), item.getCreateTime(), "价格超出容忍值范围[price="+price+"leftPrice="+leftPrice+";rightPrice="+rightPrice+"]", level.toString());
							} catch (Exception e) {
								logger.error("XC门票商品校验失败>>>"+item.getDetailId());
							}
							//logger.warn("XC门票商品价格校验失败超出容忍阀值：taskID="+item.getTask_id()+";CommodityID="+item.getCommodity_id()+"ticket_cdetail_tc:["+item.getDetail_id()+"][price="+price+"leftPrice="+leftPrice+";rightPrice="+rightPrice+"]");
							return false;
						}
					}
				}
			}
		}
		return true;
	}
	/**
	 * 产品不做校验 直接入库
	 * 但要判断相对于上次抓取是否是新增产品
	 * 新增产品  入新产品表  入产品表   入产品历史表
	*/
	@Transactional
	public boolean saveProductDirectly(TicketPdetailMt item,TicketProductMt param,boolean hasNewCommodity){
		//本次抓取产品的  rowkey  mysqlKey
		String currentRowKey = "";
		TicketProductMt existProductMt = null;
		synchronized (TicketProductMtService.class){
			ruleUtil.addTaskInfo(item.getTaskId(), item.getCreateTime(),Constant.MT_C_CODE,Constant.TICKE_BUS_TYPE,Constant.PRODUCT_LEVEL_TYPE);
			//当前product生成的rowkey
			currentRowKey = generateRowkey(item.getProductId(), item.getCreateTime(), item.getTaskId());
			//图片地址截取
			if(StringTools.isValid(item.getSnapshotAddr())){
				item.setSnapshotAddr(StringTools.getEndStringByChar(item.getSnapshotAddr(), "/"));
			}
			try {
				//通过对象查
				TicketProductMt selectParam = new TicketProductMt();
				selectParam.setProductId(item.getProductId());
				existProductMt = productMtService.findByObject(selectParam);
				dealLinkedProduct(item,existProductMt,hasNewCommodity);
				//所有数据都放在一个列族，实际上有两个列族（HB_VARIABLE_FAMILY HB_CONSTANT_FAMILY）
				if(existProductMt==null){
					try {
						item.setDetailId(currentRowKey);
						//新产品入产品表
						newProductMtService.saveByPdetailMt(item);
						//入新产品表
						productMtService.saveByPdetailMt(item);
						//仅仅update产品分析相关的新增字段
						//当产品下不存在商品时，updateByItem会抛异常，更新失败，因为更新字段均为0
						param.setId(currentRowKey);
						productMtService.update(param);
					} catch (Exception e) {
						logger.error("productItemsService>>>产品入库异常"+e.getMessage());
					}
				}else{
					//更新数据
					try {
						item.setDetailId(existProductMt.getId());
						productMtService.updateByPdetailMt(item);
						//仅仅update产品分析相关的新增字段
						param.setId(existProductMt.getId());
						productMtService.update(param);
					} catch (Exception e) {
						logger.error("productItemsService>>>产品更新异常"+e.getMessage());
					}
				}
				//入历史表
				hbentityOper.saveMTTicketProduct(item, currentRowKey,Constant.TICKET_PRODUCT_H_MT, Constant.HB_VARIABLE_FAMILY,param);
			} catch (Exception e) {
				logger.error("productItemsService>>>产品查询异常>>>"+e.getMessage());
			}

		}
		return true;
	}
	
	private int dealLinkedProduct(TicketPdetailMt item, TicketProductMt existProductMt,boolean hasNewCommodity) {
		//没有驴妈妈产品字段不处理
		if(!StringTools.isValid(item.getLvProductId())){
			return 0;
		}
		//对于已知关联关系的产品更新关联状态
		RelevanceProduct queryItem = relevanceProductService.viewRelevance(item.getLvProductId(),Constant.TICKE_BUS_TYPE);
		RelevanceProduct newItem = new RelevanceProduct();
		if(existProductMt!=null && existProductMt.getIsLink()!=null && existProductMt.getIsLink().intValue()==1){
			if(hasNewCommodity && queryItem!=null && queryItem.getProdIdMT().equals(item.getProductId())){//如果新增商品且产品关联关系未改变
				//因为抓到新商品，所以状态更新，可以人工再做商品关联
				newItem.setIsDeal(0);
				relevanceProductService.updateRelevance(newItem);
			}
			return 0;
		}
		synchronized (RelevanceProductService.class) {
			newItem.setProdId(item.getLvProductId());
			newItem.setProdIdMT(item.getProductId());
			newItem.setProdNameMT(item.getSceneryName());
			newItem.setBusinessCode(Constant.TICKE_BUS_TYPE);
			if(queryItem==null){
				relevanceProductService.insertMT(newItem);
				item.setIsLink(Constant.PRODUCT_IS_LINKED);
			}else if(!StringTools.isValid(queryItem.getProdIdMT())){
				relevanceProductService.updateMT(newItem);
				item.setIsLink(Constant.PRODUCT_IS_LINKED);
			}
		}
		return 1;
	}
	public int commodityInsertLog(TicketCdetailMt item,String rowkey){
		item.setDetailId(rowkey);
		//操作error表
		item.setErrorFlag("true");
		try {
			TicketCdetailMt existItem = cdetailMtService.findFailItemById(rowkey);
			if(existItem==null){
				return cdetailMtService.save(item);
			}else{
				return 0;
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
		
		return -1;
	}
	
	//计算产品下商品类别个数
	public int handleCommTypeNum(List<TicketCdetailMt> list){
		Set<String> set = new HashSet<>();
		for(TicketCdetailMt item:list){
			set.add(item.getCommodityType());
		}
		return set.size();
	}
	
	private TicketProductMt handelProduct(List<TicketCdetailMt> checkedDoneList) {
		TicketProductMt item = new TicketProductMt();
		//优惠商品个数
		int commPreferentialNum = 0;
		//打包商品个数
		int commPackageNum = 0;
		String packageCommType = configManager.getParamValue(Constant.TICKET_COMMODITY_STARDARD_TYPE_CONFIG, Constant.TICKET_COMMODITY_STARDARD_TYPE_CONFIG);
		//设置产品对应商品的数量
		item.setCommodityNum(checkedDoneList.size());
		for(TicketCdetailMt commItem : checkedDoneList){
			if(StringTools.isValid(commItem.getPreferential())){commPreferentialNum++;}
			if(packageCommType.contains(";"+commItem.getCommodityType().trim()+";")){commPackageNum++;}
		}
		item.setCommPreferentialNum(commPreferentialNum);
		item.setCommPackageNum(commPackageNum);
		return item;
	}
}
